package asteroids.model;

import be.kuleuven.cs.som.annotate.*;
import asteroids.ModelException;
import asteroids.util.Vector;

/**
 * A class representing asteroids in the asteroids game.
 * 
 * @author Michiel De Cuyper & Lennart De Graef
 * @version 3.0
 * 
 * @invar The mass of this SpaceObject is equal to the spherical mass of the asteroid with densitiy ASTEROIDDENSITY
 *        | this.getMass() == ASTEROIDMASS == 4 / 3 * Math.PI * Math.pow(this.getRadius(), 3) * ASTEROIDDENSITY;
 * 
 */
public class Asteroid extends SpaceObject {

	/**
	 * Basic constructor for an asteroid
	 * 
	 * @param radius
	 *            The radius of this asteroid
	 * @param velocity
	 *            The velocity of this asteroid, a vector.
	 * @param position
	 *            The position of this asteroid, a vector.
	 * @param world
	 *            The world in which this asteroid is.
	 * @throws ModelException
	 *             Throws a modelexception whenever the radius, position or world is not valid
	 *             | if( !isValidRadius(radius) || !isValidPosition(position) || !isValidWorld(world)) throw new
	 *             ModelException(errorMessage)
	 * 
	 * @effect Creates an Asteroid, calling the constructor of SpaceObject
	 *         | super(radius, velocity, position, world)
	 * @effect Sets the mass of this Asteroid equal to the AsteroidMass
	 *         | this.setMass(this.getAsteroidMass())
	 */
	public Asteroid(double radius, Vector velocity, Vector position, World world) throws ModelException {
		super(radius, velocity, position, world);
		this.setMass(this.getAsteroidMass());
	}

	/**
	 * Checks wether a given mass is valid, i.e. the given mass equals ASTEROIDMASS
	 * 
	 * @return True if and only if the given mass equals ASTEROIDMASS
	 *         | return mass == ASTEROIDMASS
	 */
	@Override
	public boolean isValidMass(double mass) {
		return mass == ASTEROIDMASS;
	}

	/**
	 * Checks wether a given radius is valid
	 * 
	 * @return True if and only if the given radius is strictly larger than 0, smaller than infinity, and is a double.
	 *         | return radius > 0 && (radius < Double.POSITIVE_INFINITY) && (radius != Double.NaN);
	 */
	@Override
	public boolean isValidRadius(double radius) {
		return (radius > 0) && (radius < Double.POSITIVE_INFINITY) && (radius != Double.NaN);
	}

	/**
	 * Returns the value ASTEROIDMASS, a value calculated based on the density of an asteroid.
	 * 
	 * @return The value ASTEROIDMASS
	 *         | return this.ASTEROIDMASS
	 */
	@Basic @Immutable
	public double getAsteroidMass() {
		return this.ASTEROIDMASS;
	}

	/**
	 * 2 final doubles, representing the density and mass of an asteroid.
	 */
	private final double ASTEROIDDENSITY = 7.8 * Math.pow(10, 12);
	private final double ASTEROIDMASS = 4 / 3 * Math.PI * Math.pow(this.getRadius(), 3) * ASTEROIDDENSITY;

}
